#include <stdio.h>
#include <pthread.h>
#include <time.h>
#include <sys\timeb.h>

/* Ordenacao bolha com flag
   @entradas:
     L: vetor de inteiros
	 N: tamanho do vetor
*/
void bubble_sort(int* L, int N){
	int flag = 0, i, aux;
	while (flag == 0)
	{
		flag = 1;
		for (i = 1; i < N; i++){
			if (L[i] < L[i - 1]){
				aux = L[i];
				L[i] = L[i - 1];
				L[i - 1] = aux;
				flag = 0;
			}
		}
	}
}

/* Ordenacao InsertionSort
   @entradas:
     L: vetor de inteiros
	 N: tamanho do vetor
*/
void insertion_sort(int L[], int N){
	int i, j, pivo;

	for (i = 1; i <= N - 1; i++){
		pivo = L[i];
		j = i - 1;
		while (j >= 0 && L[j] > pivo){
			L[j + 1] = L[j];
			j--;
		}
		L[j + 1] = pivo;
	}
}

/* Gera inteiro pseudo-aleatorio no intervalo [0,lim]
  @entradas:
    lim: limite superior do intervalo
  @saida:
    inteiro com valor entre 0 e [lim]
*/
int random_n(int lim){
	return rand() % (lim + 1);
}

/* Gera vetor de inteiros com valores entre [0 , 10*size]
  @entradas:
    size: tamanho do vetor
	@saida:
	vetor de inteiros com valores aleatórios
	variando entre 1 e 10*[size]
*/
int* random_array(int size){
	int * ret = (int*)malloc(size*sizeof(int));
	int i;
	srand(time(NULL));
	for (i = 0; i < size; i++){
		ret[i] = random_n(10*size);
	}
	return ret;
}

/* Procedimento executado pelas threads
   @entradas:
     id: numero da thread criada
*/
void *thread_process(void *id){
	long int thread_id;
	int size = 10000;
	int* array = random_array(size);
	thread_id = (long int)id+1;
	int op = 0,count = 0;
	struct timeb t_inicio, t_fim;		// Estruturas para marcar o tempo
	float diff;
	
	ftime(&t_inicio);
	if(thread_id%2 == 0){
		printf("Thread No %ld : Eu vou usar o BubbleSort!\n",thread_id);
		bubble_sort(array,size);
	}
	else{
		printf("Thread No %ld : Eu vou usar o InsertionSort!\n",thread_id);
		insertion_sort(array,size);
	}
	ftime(&t_fim);
	diff = (float)(1000.0*(t_fim.time - t_inicio.time) +
				(t_fim.millitm - t_inicio.millitm));

	printf("Thread No %ld : Tempo de execucao %f ms\n",thread_id,diff);
	pthread_exit(NULL);
}

int main(int argc,char* argv[]){
	int thread_count;
	if( argc == 2){
		//threads.exe N = N threads diferentes
		thread_count = atoi(argv[1]);
	}
	else{
		thread_count = 2;
	}
	pthread_t threads[thread_count];
	int ret_code;
	long int i;
	for( i = 0; i < thread_count; i++ ){
		printf("Main thread: Criando thread No %ld\n",i+1);
		ret_code = pthread_create(&threads[i], NULL, 
								  thread_process, (void*)i);
		if(ret_code){
          printf("ERROR; return code from pthread_create() is %d\n", ret_code);
          exit(-1);
		}
    }
	
	pthread_exit(NULL);
}